package alipay

import (
	"encoding/json"
	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
	"log"
	"time"
	"yundian/internel/app/dao"
	"yundian/internel/app/helper"
	"yundian/internel/app/helper/request"
	"yundian/internel/app/logic"
	"yundian/internel/app/models/orders"
	"yundian/internel/pkg/dingo"
	"yundian/internel/pkg/dingo/global"
	. "yundian/internel/pkg/dingo/result"
	"yundian/internel/pkg/utils"
	"yundian/internel/pkg/wechatpay"
	"yundian/internel/pkg/wxpay"
)

// ------------微信支付相关请求处理---------------//

var payClient = wxpay.NewPayClient(nil)

// HandleLogin 微信小程序登录
func HandleLogin(ctx *gin.Context) {
	param := &struct {
		Code string `form:"code" binding:"required"`
	}{}
	dingo.ErrorIf(ctx.ShouldBindQuery(param)).Unwrap()

	wc := logic.NewSettingLogic().GetPaySetting()

	respData, err := payClient.Login(param.Code, wc.AppId, wc.AppSecret)
	if err != nil {
		zap.L().Error(err.Error())
		Response(ctx)(err.Error(), CodeError, nil)(Error)
		return
	}

	// 处理业务逻辑
	loginResult, err := logic.NewWxAuthLogic().HandleLogicLogin(respData, wc.AppId)
	if err != nil {
		zap.L().Error(err.Error())
		Response(ctx)(err.Error(), CodeError, nil)(Error)
		return
	}

	// 响应给前端
	Response(ctx)("", CodeSuccess, loginResult)(OK)
}

// HandleMemberInfo 更新用户信息
func HandleMemberInfo(ctx *gin.Context) {
	param := &request.MemberInfoReq{}
	dingo.ErrorIf(ctx.ShouldBindQuery(param)).Unwrap()
	log.Println("打印测试数据-更新用户信息", param)

	userId, err := helper.GetUserIdFromCtx(ctx)
	if err != nil {
		Response(ctx)(err.Error(), CodeNeedLogin, nil)(Unauthorized)
		return
	}
	openid, err := helper.GetUserNameFromCtx(ctx)
	if err != nil {
		Response(ctx)(err.Error(), CodeNeedLogin, nil)(Unauthorized)
		return
	}

	// 获取sessionKey
	rdbSessionKey := utils.Join(openid, "-sessionKey")
	sessionKey := global.Rdb.Get(ctx, rdbSessionKey).Val()
	sign := wechatpay.SHA1(param.RawData, sessionKey)

	log.Println("sessionKey-sign", rdbSessionKey, sessionKey, sign)
	if sign != param.Signature {
		Response(ctx)("签名不一致", CodeError, nil)(Error)
		return
	}

	wc := logic.NewSettingLogic().GetPaySetting()

	// 解密微信数据
	pc := wechatpay.NewWXUserDataCrypt(wc.AppId, sessionKey)
	userInfo, err := pc.Decrypt(param.EncryptedData, param.Iv)
	if err != nil {
		Response(ctx)("解密失败", CodeError, err.Error())(Error)
		return
	}
	log.Println("解密后的用户信息", userInfo)

	// 更新用户信息逻辑
	logic.NewWxAuthLogic().UpdateMemberInfo(userInfo, userId)

	Response(ctx)("获取会员授权信息成功", CodeSuccess, userInfo)(OK)
}

// HandleMemberPhone 更新用户信息
func HandleMemberPhone(ctx *gin.Context) {
	param := &request.MemberInfoReq{}
	dingo.ErrorIf(ctx.ShouldBindJSON(param)).Unwrap()
	log.Println("打印测试数据-更新用户信息", param)

	var phoneInfo = map[string]interface{}{}
	if param.EncryptedData == "" && param.Iv == "" {
		Response(ctx)("获取会员授权信息成功", CodeSuccess, phoneInfo)(OK)
		return
	}

	userId, err := helper.GetUserIdFromCtx(ctx)
	if err != nil {
		Response(ctx)(err.Error(), CodeNeedLogin, nil)(Unauthorized)
		return
	}
	openid, err := helper.GetUserNameFromCtx(ctx)
	if err != nil {
		Response(ctx)(err.Error(), CodeNeedLogin, nil)(Unauthorized)
		return
	}

	// 获取sessionKey
	rdbSessionKey := utils.Join(openid, "-sessionKey")
	sessionKey := global.Rdb.Get(ctx, rdbSessionKey).Val()

	log.Println("打印测试session", openid, rdbSessionKey, sessionKey)

	// 解密微信数据
	str, err := wechatpay.Dncrypt(param.EncryptedData, sessionKey, param.Iv)

	if err != nil {
		Response(ctx)("解密失败", CodeError, err.Error())(Error)
		return
	}
	log.Println("解密后的用户信息", str)

	_ = json.Unmarshal([]byte(str), &phoneInfo)

	// 更新用户信息逻辑
	logic.NewWxAuthLogic().UpdateMemberPhone(phoneInfo["phoneNumber"].(string), userId)

	Response(ctx)("获取会员授权信息成功", CodeSuccess, phoneInfo)(OK)
}

// HandleUnifiedOrder 统一下单-押金支付并生成支付签名V2版本
func HandleUnifiedOrder(ctx *gin.Context) {
	userId, err := helper.GetUserIdFromCtx(ctx)
	log.Println("打印统一下订单，请求参数处理", userId, err)
	if err != nil {
		Response(ctx)(err.Error(), CodeNeedLogin, nil)(Unauthorized)
		return
	}
	// 请求参数处理
	param := &request.CreateOrderReq{}
	dingo.ErrorIf(ctx.ShouldBindJSON(param)).Unwrap()
	param.ClientIp = ctx.ClientIP()
	param.UserId = userId

	log.Println("打印统一下订单，请求参数处理", param)

	if param.Openid == "" || param.DeviceSn == "" {
		Response(ctx)("参数错误,请重新扫码", CodeError, nil)(OK)
		return
	}

	// 验证是否是黑名单
	if b := helper.CheckOpenidStatus(param.Openid); b { // 100006
		Response(ctx)("CodeInvalidOpenid", CodeInvalidOpenid, nil)(OK)
		return
	}

	// 判断是否有订单
	orderInfo := dao.NewOrderDao().GetOrderInfoByOpenidAndSn(param.Openid, param.DeviceSn).Unwrap().(*orders.OrderModel)
	if orderInfo.State == 2 { // 100007
		Response(ctx)("CodeOrderExits", CodeOrderExits, orderInfo)(OK)
		return
	}

	// 下订单业务逻辑
	orderLogic := logic.NewOrderLogic()
	respData, err := orderLogic.HandleWxUnifiedOrder(param)
	if err != nil {
		Response(ctx)(err.Error(), CodeError, respData)(Error)
		return
	}
	resultData := orderLogic.HandleMakeSign(respData) // 二次签名
	Response(ctx)("", CodeSuccess, resultData.ToJson())(OK)
}

// HandleEndOrder 结束订单
func HandleEndOrder(ctx *gin.Context) {
	param := &request.CloseOrderReq{}
	log.Println("结束订单信息：")
	dingo.ErrorIf(ctx.ShouldBindJSON(param)).Unwrap()
	param.EndTime = time.Now().Unix()
	log.Println("结束订单信息：", param)
	settResp := logic.NewOrderLogic().HandleWxEndOrder(param)

	Response(ctx)("", CodeSuccess, settResp)(OK)
}

// HandleEndOrder 结束订单本地测试
func HandleCloseOrderTest(ctx *gin.Context) {
	param := &request.CloseOrderReq{}
	dingo.ErrorIf(ctx.ShouldBindJSON(param)).Unwrap()
	param.EndTime = time.Now().Unix()

	settResp := logic.NewOrderLogic().HandleWxEndOrder(param)

	Response(ctx)("", CodeSuccess, settResp)(OK)
}
